// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.

package org.jetbrains.uast.kotlin

import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNamedElement
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.internal.DelegatedMultiResolve

@ApiStatus.Internal
class KotlinUQualifiedReferenceExpression(
    override val sourcePsi: KtDotQualifiedExpression,
    givenParent: UElement?
) : KotlinAbstractUExpression(givenParent), UQualifiedReferenceExpression, DelegatedMultiResolve,
    KotlinUElementWithType, KotlinEvaluatableUElement {

    private var receiverPart: Any? = UNINITIALIZED_UAST_PART
    private var selectorPart: Any? = UNINITIALIZED_UAST_PART

    override val receiver: UExpression
        get() {
            if (receiverPart == UNINITIALIZED_UAST_PART) {
                receiverPart = baseResolveProviderService.baseKotlinConverter.convertOrEmpty(
                    sourcePsi.receiverExpression,
                    this
                )
            }
            return receiverPart as UExpression
        }

    override val selector: UExpression
        get() {
            if (selectorPart == UNINITIALIZED_UAST_PART) {
                selectorPart = baseResolveProviderService.baseKotlinConverter.convertOrEmpty(
                    sourcePsi.selectorExpression,
                    this
                )
            }
            return selectorPart as UExpression
        }

    override val accessType = UastQualifiedExpressionAccessType.SIMPLE

    override fun resolve(): PsiElement? = sourcePsi.selectorExpression?.let { baseResolveProviderService.resolveToDeclaration(it) }

    override val resolvedName: String?
        get() = (resolve() as? PsiNamedElement)?.name

    override val referenceNameElement: UElement?
        get() = when (val selector = selector) {
            is UCallExpression -> selector.methodIdentifier
            else -> super.referenceNameElement
        }
}
